package org.geektimes.projects.user.web.filter;


import org.geektimes.context.ComponentContext;
import org.geektimes.web.mvc.FrontControllerServlet;
import org.geektimes.web.mvc.controller.Controller;

import javax.annotation.Resource;
import javax.servlet.*;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @ClassName: ControllerFilter
 * @Description:
 * @Author: Hades
 * @created: 2021/03/10 00:36
 * @Version:1.0
 */
public class ControllerFilter implements Filter {

    private AtomicBoolean injectBoolean = new AtomicBoolean(false);

    private ServletContext servletContext;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.servletContext = filterConfig.getServletContext();
    }

    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        if (!injectBoolean.get()) {
            Map<String, Controller> controllerMap = FrontControllerServlet.getControllerMap();
            controllerMap.values().stream().forEach(controller -> {
                Field[] fields = controller.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (!field.isAnnotationPresent(Resource.class)) {
                        continue;
                    }
                    Resource resource = field.getAnnotation(Resource.class);
                    Object lookUpObj = ComponentContext.getInstance().getComponent(resource.name());
                    field.setAccessible(true);
                    try {
                        field.set(controller, lookUpObj);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            });
            injectBoolean.set(true);
        }
        // 执行过滤链
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}
